package com.evildog.workspace.life.application.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evildog.workspace.common.util.WsAssert;
import com.evildog.workspace.dependencies.mybatis.base.TableLinkService;
import com.evildog.workspace.dependencies.mybatis.object.QueryConditionDTO;
import com.evildog.workspace.life.application.bo.AlbumsPhotoBO;
import com.evildog.workspace.life.application.bo.PhotoBO;
import com.evildog.workspace.life.application.bo.PhotoListBO;
import com.evildog.workspace.life.application.convert.PhotoConvert;
import com.evildog.workspace.life.application.dto.PhotoDTO;
import com.evildog.workspace.life.application.dto.PhotoListDTO;
import com.evildog.workspace.life.application.dto.PhotoStarDTO;
import com.evildog.workspace.life.application.entity.Photo;
import com.evildog.workspace.life.application.entity.PhotoListDO;
import com.evildog.workspace.life.application.entity.PhotoTag;
import com.evildog.workspace.life.application.enums.LifeCustomExceptionDesc;
import com.evildog.workspace.life.application.mapper.AlbumMapper;
import com.evildog.workspace.life.application.mapper.PhotoMapper;
import com.evildog.workspace.life.application.mapper.PhotoTagMapper;
import com.evildog.workspace.life.application.service.PhotoService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimaps;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
@AllArgsConstructor
public class PhotoServiceImpl extends ServiceImpl<PhotoMapper, Photo> implements PhotoService {

    private final PhotoTagMapper photoTagMapper;
    private final AlbumMapper albumMapper;
    private final TableLinkService tableLinkService;

    @Override
    public List<AlbumsPhotoBO> getList(List<QueryConditionDTO> queryCondition, PhotoListDTO dto) {
        List<PhotoListDO> photoList = this.baseMapper.getList(queryCondition, dto);

        // key localDate value List<PhotoListDO>
        ImmutableListMultimap<LocalDate, PhotoListDO> mapPhotoList = Multimaps.index(photoList, photo -> Objects.requireNonNull(photo).getCreateTime().toLocalDate());

        List<Long> photoIds = new ArrayList<>();
        photoList.forEach(photoListDO -> photoIds.add(photoListDO.getId()));

        List<PhotoTag> photoTagList = tableLinkService.getLinkList(photoTagMapper,
                PhotoTag::getPhotoId, photoIds
        );

        List<AlbumsPhotoBO> result = new ArrayList<>();

        // key photoId value List<PhotoTag>
        ImmutableListMultimap<Long, PhotoTag> mapPhotoTagMap = Multimaps.index(photoTagList, PhotoTag::getPhotoId);

        mapPhotoList.asMap().forEach((localDate, list) -> {
            List<PhotoListBO> photoListBOList = PhotoConvert.INSTANCE.convert(list);

            photoListBOList.forEach(photoListBO -> {
                ImmutableList<PhotoTag> mapList = mapPhotoTagMap.get(photoListBO.getId());
                photoListBO.setPhotoTags(
                        PhotoConvert.INSTANCE.convertBoList(mapList)
                );
            });
            result.add(
                    new AlbumsPhotoBO()
                            .setDate(localDate)
                            .setPhotoList(photoListBOList));

        });


        return result;
    }

    @Override
    public PhotoBO getDetailById(Long id) {
        Photo photo = this.getById(id);
        Assert.notNull(photo, "photo is null!");
        return PhotoConvert.INSTANCE.convert(photo);
    }

    @Override
    public boolean save(PhotoDTO dto) {
        Long albumId = dto.getAlbumId();
        WsAssert.notNull(albumMapper.selectById(albumId), LifeCustomExceptionDesc.ALBUM_NOT_FOUND);


        List<Photo> photos = new ArrayList<>();
        List<String> urls = dto.getUrls();

        urls.forEach(url -> {
            photos.add(new Photo()
                    .setAlbumId(albumId)
                    .setUrl(url)
            );
        });


        return saveBatch(photos);
    }

    @Override
    public boolean updateStar(Long id, PhotoStarDTO convert) {
        Photo oldPhoto = getById(id);
        Assert.notNull(oldPhoto, "photo is null!");
        Photo newPhoto = new Photo()
                .setStar(convert.getStar())
                .setId(id);
        return updateById(newPhoto);
    }


    @Override
    public boolean updateById(Long id, PhotoDTO dto) {
        Photo oldPhoto = getById(id);
        Assert.notNull(oldPhoto, "photo is null!");
        Photo newPhoto = PhotoConvert.INSTANCE.convert(dto);
        newPhoto.setId(id);
        return updateById(newPhoto);
    }
}
